package fnsvr

import (
	"encoding/binary"
	"encoding/json"
	"fmt"
	"math"
	"math/rand"
	"runtime/debug"
	"strconv"
	"strings"
	"time"

	"github.com/google/uuid"
)

// any类型转换为字符串
func AnyToString(any any) string {
	switch v := any.(type) {
	case string:
		return v
	case int:
		return strconv.Itoa(v)
	case int8:
		return strconv.Itoa(int(v))
	case int16:
		return strconv.Itoa(int(v))
	case int32:
		return strconv.Itoa(int(v))
	case int64:
		return strconv.FormatInt(v, 10)
	case uint:
		return strconv.FormatUint(uint64(v), 10)
	case uint8:
		return strconv.FormatUint(uint64(v), 10)
	case uint16:
		return strconv.FormatUint(uint64(v), 10)
	case uint32:
		return strconv.FormatUint(uint64(v), 10)
	case uint64:
		return strconv.FormatUint(v, 10)
	case float32:
		return strconv.FormatFloat(float64(v), 'f', -1, 32)
	case float64:
		return strconv.FormatFloat(v, 'f', -1, 64)
	case bool:
		return strconv.FormatBool(v)
	case []string:
		b, _ := json.Marshal(v)
		return string(b)
	case []int:
		b, _ := json.Marshal(v)
		return string(b)
	case []int8:
		b, _ := json.Marshal(v)
		return string(b)
	case []int16:
		b, _ := json.Marshal(v)
		return string(b)
	case []int32:
		b, _ := json.Marshal(v)
		return string(b)
	case []int64:
		b, _ := json.Marshal(v)
		return string(b)
	case []uint:
		b, _ := json.Marshal(v)
		return string(b)
	case []uint8:
		b, _ := json.Marshal(v)
		return string(b)
	case []uint16:
		b, _ := json.Marshal(v)
		return string(b)
	case []uint32:
		b, _ := json.Marshal(v)
		return string(b)
	case []uint64:
		b, _ := json.Marshal(v)
		return string(b)
	case []float32:
		b, _ := json.Marshal(v)
		return string(b)
	case []float64:
		b, _ := json.Marshal(v)
		return string(b)
	case []bool:
		b, _ := json.Marshal(v)
		return string(b)
	case []interface{}:
		b, _ := json.Marshal(v)
		return string(b)
	default:
		return fmt.Sprintf("%+v", any)
	}
}

// 生成32位guid
func NewGuid() string {
	// 生成新的 UUID
	newUUID := uuid.New()
	guid := newUUID.String()

	// 将 UUID 转换为字符串并去掉 '-'
	return strings.ReplaceAll(guid, "-", "")
}

// 生成int64类型的guid
func NewGuidInt64() (int64, error) {
	buf := make([]byte, 8)

	// 使用 rand.Read 填充随机数据
	_, err := rand.Read(buf)
	if err != nil {
		return 0, err
	}

	// 将字节转换为 int64
	var re = int64(binary.BigEndian.Uint64(buf))
	if re < 0 {
		re = -re
	}
	return re, nil
}

const epsilon = 1e-9 // 定义一个很小的误差范围

// 浮点数相等判断
func AlmostEqual(a, b float64) bool {
	return math.Abs(a-b) < epsilon
}

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")

// 生成指定长度随机字符串
func GenerateRandomString(length int) string {
	b := make([]rune, length)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

// 安全协程
func GoSafe(routineName string, fun func()) {
	defer func() {
		if r := recover(); r != nil {
			errMsg := fmt.Sprintf("GoSafe routineName:%s recovered from panic: %v, stack: %s", routineName, r, debug.Stack())
			Log().Error(errMsg)
		}
	}()

	fun()
}

// 安全协程,循环
// stopCh 控制循环结束的管道，当管道被关闭时退出循环
func GoSafeLoop(
	routineName string,
	fun func(),
	interval time.Duration,
	stopCh chan struct{},
	stopEndCh chan struct{},
) {
	ticker := time.NewTicker(interval)
	defer ticker.Stop()

	doFunc := func() {
		defer func() {
			if r := recover(); r != nil {
				errMsg := fmt.Sprintf("GoSafeLoop routineName:%s recovered from panic: %v, stack: %s", routineName, r, debug.Stack())
				Log().Error(errMsg)
			}
		}()

		fun()
	}

	for {
		select {
		case <-ticker.C:
			doFunc()
		case <-stopCh:
			close(stopEndCh)
			return
		}
	}
}
